from flask import Flask,session, g, render_template, request, jsonify
import config
import base64
import time
import requests
import os # 新增导入
from exts import db
from models import UserModel # 添加 Text 模型的导入
from blueprints.qa import bp as qa_bp
from blueprints.auth import bp as auth_bp
from blueprints.content import bp as content_bp
from blueprints.routes import bp as routes_bp
from analysis import text_analyzer  # 你的分析函数
from flask_migrate import Migrate
from sqlalchemy import event
from sqlalchemy.engine import Engine
app = Flask(__name__)
# 绑定配置文件
app.config.from_object(config)

db.init_app(app)

migrate = Migrate(app, db)


@event.listens_for(Engine, "connect")
def set_sqlite_pragma(dbapi_connection, connection_record):
    cursor = dbapi_connection.cursor()
    cursor.execute("PRAGMA foreign_keys=ON")
    cursor.close()
# 数据库初始化逻辑
with app.app_context():
    # 确保数据库目录存在
    db_dir = os.path.join(app.root_path, 'sql_file')
    if not os.path.exists(db_dir):
        os.makedirs(db_dir)
        print(f"[INFO] 已创建数据库目录: {db_dir}")

    # 初始化数据库
    db_path = os.path.join(db_dir, 'bv.db')
    if not os.path.exists(db_path):
        print(f"[INFO] 正在创建数据库文件: {db_path}")
        open(db_path, 'a').close()  # 创建空文件

    # 创建所有表
    try:
        db.create_all()
        print("[SUCCESS] 数据库表结构已创建")
    except Exception as e:
        print(f"[ERROR] 创建表失败: {str(e)}")
        raise
# 注册蓝图
app.register_blueprint(qa_bp)
app.register_blueprint(auth_bp)
app.register_blueprint(content_bp)
app.register_blueprint(routes_bp)


# flask db init：只需要执行一次
# flask db migrate：将orm模型生成迁移脚本
# flask db upgrade：将迁移脚本映射到数据库中


@app.before_request
def my_before_request():
    user_id = session.get("user_id")
    if user_id:
        user = UserModel.query.get(user_id)
        setattr(g, "user", user)
    else:
        setattr(g, "user", None)


@app.context_processor
def my_context_processor():
    return {"user": g.user}


@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        if request.form.get('text'):
            text = request.form['text']
            result = text_analyzer.analyze_text(text)
            return jsonify(result)  # 直接返回JSON给前端
        elif 'file' in request.files:
            file = request.files['file']
            if file.filename.endswith('.txt'):
                print("yes")
                text = file.read().decode('utf-8')
                result = text_analyzer.analyze_text(text)
                return jsonify(result)
            else:
                return jsonify({"error": "Please upload a .txt file."}), 400
        else:
            return jsonify({"error": "No text or file provided."}), 400
    return render_template('index.html')  # 初始页面


@app.route('/result')
def result():
    return render_template('result.html')


#@app.route("/index_content")
#def index_content():
#    return render_template("index_content.html")

BAIDU_API_KEY = 'IHDYJrawgNKXNDm0WO3hAxKT'
BAIDU_SECRET_KEY = 'aRqCChcN80O84ADL6Nl8chTmdHVzLOfg'

TOKEN_CACHE = {
    'token': None,
    'expires': 0
}


def get_access_token():
    """获取并缓存百度语音API的访问令牌"""
    # 检查缓存有效性（提前5分钟过期）
    if TOKEN_CACHE['token'] and time.time() < TOKEN_CACHE['expires']:
        return TOKEN_CACHE['token']

    # 请求参数
    params = {
        "grant_type": "client_credentials",
        "client_id": BAIDU_API_KEY,
        "client_secret": BAIDU_SECRET_KEY
    }

    try:
        # 发送请求
        response = requests.get(
            "https://aip.baidubce.com/oauth/2.0/token",
            params=params,
            timeout=10  # 添加超时设置
        )
        response.raise_for_status()  # 检查HTTP状态码

        # 解析响应
        data = response.json()

        # 错误处理
        if 'error' in data:
            error_msg = data.get('error_description', '未知错误')
            raise Exception(f"Token获取失败: {data['error']} - {error_msg}")

        # 更新缓存
        TOKEN_CACHE['token'] = data['access_token']
        TOKEN_CACHE['expires'] = time.time() + data['expires_in'] - 300  # 提前5分钟过期

        print(f"Token更新成功，有效期至：{time.ctime(TOKEN_CACHE['expires'])}")
        return TOKEN_CACHE['token']

    except requests.exceptions.RequestException as e:
        raise Exception(f"网络请求失败: {str(e)}")
    except KeyError:
        raise Exception("无效的API响应格式")
    except Exception as e:
        raise Exception(f"获取Token时发生未知错误: {str(e)}")
# 调用百度语音合成 API
# 修改后的语音合成核心代码
def synthesize_speech(text):
    access_token = get_access_token()
    url = "https://tsn.baidu.com/text2audio"  # 修正为HTTPS协议

    # 对文本进行URL编码
    from urllib.parse import quote
    encoded_text = quote(text)

    params = {
        "tex": encoded_text,  # 使用编码后的文本
        "lan": "zh",
        "cuid": "86958608dde74d92bfd7a9ce849df2e2",
        "tok": access_token,
        "ctp": 1,
        "aue": 3,
        "vol": 5,
        "per": 3
    }

    try:
        response = requests.get(  # 改用GET请求
            url,
            params=params,  # 参数通过URL查询字符串传递
            timeout=15
        )

        # 增强响应验证
        if response.status_code != 200:
            raise Exception(f"HTTP错误 {response.status_code}")

        content_type = response.headers.get('Content-Type', '')

        if 'audio/mp3' in content_type:
            return response.content
        elif 'application/json' in content_type:
            error_data = response.json()
            error_msg = error_data.get('err_msg', '未知错误')
            error_code = error_data.get('err_no', '未知错误码')
            raise Exception(f"合成失败[{error_code}]: {error_msg}")
        else:
            raise Exception(f"未知响应格式: {content_type}")

    except requests.exceptions.SSLError as e:
        raise Exception(f"SSL证书错误: {str(e)}")
    except requests.exceptions.Timeout:
        raise Exception("请求超时（15秒）")
    except requests.exceptions.RequestException as e:
        raise Exception(f"网络请求异常: {str(e)}")


@app.route('/speak', methods=['POST'])
def speak():
    text = request.json.get("text", "")
    if not text:
        return jsonify({"error": "text参数必填"}), 400

    try:
        start_time = time.time()
        print(f"开始合成 | 文本: {text[:20]}...")  # 打印前20字符

        audio_data = synthesize_speech(text)

        # 宽松的音频验证
        if len(audio_data) < 1024:
            raise ValueError("音频数据过短（可能无效）")

        audio_base64 = base64.b64encode(audio_data).decode('utf-8')
        print(f"合成成功 | 长度: {len(text)}字符 | 耗时: {time.time() - start_time:.2f}s")
        return jsonify({"audio": audio_base64})

    except Exception as e:
        import logging
        logging.error("语音合成失败详情：", exc_info=True)
        return jsonify({
            "error": str(e),
            "advice": "请检查：1.网络连接 2.文本长度（<1024字） 3.控制台配额"
        }), 500




if __name__ == '__main__':
    app.run()